package com.ffmpeg.util.infra.util;

import java.io.*;
import java.util.*;

import com.ffmpeg.util.infra.config.FileConfigProperties;
import com.ffmpeg.util.infra.config.InitConfig;
import com.ffmpeg.util.infra.constant.DealWhenExistEnum;
import com.ffmpeg.util.infra.constant.FileConstant;
import com.ffmpeg.util.infra.handle.file.IDealWhenExistHandle;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * @author :wm
 * @description : Ffmpeg工具类
 */
@Component
public class FfmpegUtils {
    private final static Logger logger = LoggerFactory.getLogger(FfmpegUtils.class);

    /**
     * 默认压缩命令
     */
    public final static String DEFAULT_COMPRESS_COMMAND = "%s -i %s -c:v libx265 -x265-params crf=18 %s";

    /**
     * 默认压缩命令:segment_time表示每个视频的时间长度
     */
    public final static String DEFAULT_SHARDING_COMMAND = "%s -i %s -c copy -map 0 -f segment -segment_time %s -reset_timestamps 1 %s";

    /**
     * 默认合并命令 %s分别代表 ffmpeg 合并文档地址 合并视频地址
     */
    public final static String DEFAULT_MERGE_COMMAND = "%s -f concat -i %s -c copy %s";

    private FileConfigProperties fileConfigProperties;

    @Autowired
    public void setFileConfigProperties(FileConfigProperties fileConfigProperties) {
        this.fileConfigProperties = fileConfigProperties;
    }

    private InitConfig initConfig;

    @Autowired
    public void setInitConfig(InitConfig initConfig) {
        this.initConfig = initConfig;
    }

    public String buildDefaultCompressCommand(String ffmpegPath, String sourceFilePath, String targetFilePath) {
        if (StringUtils.isEmpty(sourceFilePath)) {
            logger.error("source file path is empty");
            return StringUtils.EMPTY;
        }
        return String.format(DEFAULT_COMPRESS_COMMAND, Optional.ofNullable(ffmpegPath).orElse(fileConfigProperties.getPrefixFfmpegPath()),
                sourceFilePath, targetFilePath);
    }

    public IDealWhenExistHandle getDealWhenExistHandle() {
        return Optional.ofNullable(initConfig.getDealWhenExistHandleMap().get(fileConfigProperties.getDealWhenExistEnum()))
                .orElse(initConfig.getDealWhenExistHandleMap().get(DealWhenExistEnum.DELETE));
    }

    /**
     * 生成合并用的txt
     *
     * @param dirPath 目录
     * @param prefix  前缀
     * @param suffix  后缀(文件格式)
     */
    public Boolean generatorMergeTxtByDir(String dirPath, String prefix, String suffix) {
        Assert.isTrue(StringUtils.isNotEmpty(dirPath) && StringUtils.isNotEmpty(suffix), "error.args.empty");
        Assert.isTrue(StringUtils.isNotEmpty(prefix), "error.prefix.empty");
        File file = new File(dirPath);
        File[] files = file.listFiles((File item) -> StringUtils.startsWith(item.getName(), prefix));
        if (Objects.isNull(files)) {
            return false;
        }
        Arrays.sort(files, Comparator.comparingDouble((fileItem) -> ComparatorUtil.ChangeToDouble.applyAsDouble(fileItem.getName(), prefix, suffix)));
        //构建merge.txt文本
        StringBuilder stringBuilder = new StringBuilder();
        for (File fileItem : files) {
            stringBuilder.append(FileConstant.FILE).append(StringUtils.SPACE).append(fileItem.getName())
                    .append(FileConstant.Symbol.LINE_SEPARATOR);
        }
        logger.info("merge.txt: {}", stringBuilder.toString());
        String mergePath = dirPath + fileConfigProperties.getMergeTxtPath();
        File mergeFile = new File(mergePath);
        if (mergeFile.exists() && mergeFile.delete()) {
            logger.info("file {} delete success", mergePath);
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(mergePath))) {
            // 将格式化后的内容写入到文本文件中
            writer.write(stringBuilder.toString());
        } catch (IOException ioException) {
            logger.error("generator {} error", FileConstant.MERGE_FILE);
            return false;
        }
        return true;
    }
}
